package ui;

import io.GPSPoint;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.openstreetmap.gui.jmapviewer.JMapViewer;
import org.openstreetmap.gui.jmapviewer.OsmFileCacheTileLoader;
import org.openstreetmap.gui.jmapviewer.OsmTileLoader;
import org.openstreetmap.gui.jmapviewer.events.JMVCommandEvent;
import org.openstreetmap.gui.jmapviewer.interfaces.JMapViewerEventListener;
import org.openstreetmap.gui.jmapviewer.interfaces.MapMarker;

import session.Session;

import actions.Settings;

@SuppressWarnings("serial")
public class OSMPanel2 extends JMapViewer implements PropertyChangeListener, JMapViewerEventListener { 
	
	private final CurrentZoom currentZoom;
	private List<MapMarker> oldMarkers = new ArrayList<MapMarker>();
	private Map<String, List<GPSPoint>> gpsTracks;
	private final Session session;;

	public OSMPanel2 (CurrentZoom currentZoom, Session session)  {
		this.currentZoom = currentZoom;
		this.session = session;
		addJMVListener(this);
		  try {
			  setTileLoader(new OsmFileCacheTileLoader(this));
		  } catch (Exception e) {
			  System.err.println("Cannot use cached file loader.");
			  e.printStackTrace();
			  setTileLoader(new OsmTileLoader(this));
		  }
	      setZoomContolsVisible(false);
		  setZoom(12);
		  Settings.getInstance().getPropertyChangeSupport().addPropertyChangeListener(this);
	}
	
	@Override
	public void processCommand(JMVCommandEvent arg0) {
		//System.err.println(arg0);
	}

	@Override
	public void propertyChange(PropertyChangeEvent evt) {
		if (evt.getPropertyName().equals(Settings.getInstance().LOADED_GPS_FILES)) {
			gpsTracks = (Map<String, List<GPSPoint>>) evt.getNewValue();
			System.err.println("Redrawing the markers");
			reloadMarkers(new long[] {0, Long.MAX_VALUE});
		} else if (evt.getPropertyName().equals(Settings.getInstance().RANGE_CHANGE)) {
			long[] inselection = (long[]) evt.getNewValue();
			reloadMarkers(inselection);
		}
	}

	private void reloadMarkers(long[] inselection) {
		for (MapMarker mapMarker : oldMarkers) {
			removeMapMarker(mapMarker);
			oldMarkers = new ArrayList<MapMarker>();
		}
		removeMapMarker(null);
		if (gpsTracks != null) {
			for (Map.Entry<String, List<GPSPoint>> entry : gpsTracks.entrySet()) {
				List<GPSPoint> points = entry.getValue();
				for (GPSPoint gpsPoint : points) {
					long time = gpsPoint.getTime();
					if (inselection[0] < time && time < inselection[1]) {
						if (session.isMapFollowsChart()) {
							GPSMarkerPoint marker = new GPSMarkerPoint(gpsPoint, currentZoom);
							oldMarkers.add(marker);
							addMapMarker(marker);
						}
					}
				}
			}
		}
		if (session.isMapFollowsChart()) {
			setZoom(12);
			setDisplayToFitMapMarkers();
		}
		
		//Also adding the non-selected points. Nicer e.g. when you run loops
		if (gpsTracks != null) {
			for (Map.Entry<String, List<GPSPoint>> entry : gpsTracks.entrySet()) {
				List<GPSPoint> points = entry.getValue();
				for (GPSPoint gpsPoint : points) {
					long time = gpsPoint.getTime();
					if ((inselection[0] < time && time < inselection[1]) == false) {
						GPSMarkerPoint marker = new GPSMarkerPoint(gpsPoint, currentZoom);
						oldMarkers.add(marker);
						addMapMarker(marker);
					}
					if (session.isMapFollowsChart() == false) {
						GPSMarkerPoint marker = new GPSMarkerPoint(gpsPoint, currentZoom);
						oldMarkers.add(marker);
						addMapMarker(marker);
					}
				}
			}
		}
	}
	
}